package com.chebaohui.iqs.service.impl.deal.union.util;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import com.chebaohui.iqs.service.impl.deal.union.entity.*;
import com.chebaohui.iqs.service.impl.deal.union.sdk.*;

/**
 * 产品：跳转网关支付产品<br>
 * 
 * @author xielonghai
 */
public class PayConsume {

	public static final String root_path = System.getProperty("user.dir") + File.separator + "config" + File.separator+"union"+ File.separator;//银联配置信息根目录

	/**
	 * 保险公司相关信息---构造
	 * 
	 * @param code
	 * @param orderId
	 * @return
	 */
	public static Company getCompany(String config_path, String orderNo, String amounts) throws Exception {
		Company company = new Company();

		company.setOrderId(orderNo);// 商户订单号，8-40位数字字母，不能含“-”或“_”

		String time = TimeTool.timeToTime(TimeTool.getCurrentTime(TimeTool.sdf_default), TimeTool.sdf_default,
				TimeTool.sdf_union);

		company.setPayTimeout(TimeTool.getTimeout(time, TimeTool.sdf_union, "15"));// 订单超时时间。yyyyMMddHHmmss

		company.setTxnTime(time);

		company.setTxnAmt(Integer.valueOf(amounts));// 交易金额，单位分

		String path = root_path + config_path + File.separator;
		Properties pro = ReadProperties.getPropertiesFromPath(path + "acp_sdk.properties");
		if (null == pro)
			throw new Exception("配置文件为空");

		if (null != path) {
			company.setBackUrl(pro.getProperty("back_url"));// 后台通知地址
			company.setFrontUrl(pro.getProperty("front_url"));// 前台通知地
		}
		company.setMerId(pro.getProperty("bussess_merid"));// 商户号码
		company.setUnion(getUnion(config_path));

		return company;
	}

	/**
	 * 相关证书路径配置
	 * 
	 * @param config_path
	 *            config文件名为config_path的目录下
	 * @return
	 * @throws Exception
	 */
	public static Union getUnion(String config_path) throws Exception {
		Union union = new Union();
		String path = root_path + config_path + File.separator;
		Properties pro = ReadProperties.getPropertiesFromPath(path + "acp_sdk.properties");
		if (null == pro)
			throw new Exception("配置文件为空");

		union.setCertPath(path + pro.getProperty(ProKey.SDK_SIGNCERT_PATH));
		union.setCerPwd(pro.getProperty(ProKey.SDK_SIGNCERT_PWD));
		union.setMiddleCertPath(path + pro.getProperty(ProKey.SDK_MIDDLECERT_PATH));
		union.setRootCertPath(path + pro.getProperty(ProKey.SDK_ROOTCERT_PATH));
		union.setEncryptCertPath(path + pro.getProperty(ProKey.SDK_ENCRYPTCERT_PATH));
		union.setValidateCertDir(path + pro.getProperty(ProKey.SDK_VALIDATECERT_DIR));
		union.setFrontRequestUrl(pro.getProperty(ProKey.SDK_FRONT_URL));
		union.setSingleQueryUrl(pro.getProperty(ProKey.SDK_SIGNQ_URL));
		return union;
	}

	/**
	 * 设置double的小数位数
	 * 
	 * @param db
	 *            需设置值
	 * @param i
	 *            小数位数
	 * @return
	 */
	public static double setDouble(double db, int i) {
		return new BigDecimal(db).setScale(i, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 银联支付后信息转换
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static void getUnionQuery(Map<String, String> data, Object obj) throws Exception {
		BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
		PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
		for (PropertyDescriptor property : propertyDescriptors) {
			String key = property.getName();
			if (data.containsKey(key)) {
				Object value = data.get(key);
				// 得到property对应的setter方法
				Method setter = property.getWriteMethod();
				setter.invoke(obj, value);
			}
		}
	}

	/**
	 * 银联支付查询--请求参数设置
	 * 
	 * @param orderId
	 * @param txnTime
	 * @param merId
	 * @return
	 */
	public static Map<String, String> getQueryData(Company company) {
		Map<String, String> data = new HashMap<String, String>();

		/*** 银联全渠道系统，产品参数，除了encoding自行选择外其他不需修改 ***/
		data.put("version", UnionConfig.version); // 版本号
		data.put("encoding", UnionConfig.encoding); // 字符集编码 可以使用UTF-8,GBK两种方式
		data.put("signMethod", UnionConfig.signMethod); // 签名方法
		data.put("txnType", "00"); // 交易类型 00-默认
		data.put("txnSubType", "00"); // 交易子类型 默认00
		data.put("bizType", "000201"); // 业务类型 B2C网关支付，手机wap支付

		/*** 商户接入参数 ***/
		data.put("merId", company.getMerId()); // 商户号码，请改成自己申请的商户号或者open上注册得来的777商户号测试
		data.put("accessType", "0"); // 接入类型，商户接入固定填0，不需修改

		/*** 要调通交易以下字段必须修改 ***/
		data.put("orderId", company.getOrderId()); // ****商户订单号，每次发交易测试需修改为被查询的交易的订单号
		data.put("txnTime", company.getTxnTime()); // ****订单发送时间，每次发交易测试需修改为被查询的交易的订单发送时间

		return data;
	}

	/**
	 * 银联支付--请求参数设置
	 * 
	 * @param Company
	 *            公司相关信息
	 * @return
	 */
	public static Map<String, String> getPayData(Company company) {
		Map<String, String> requestData = new HashMap<String, String>();
		/*** 银联全渠道系统，产品参数，除了encoding自行选择外其他不需修改 ***/
		requestData.put("version", UnionConfig.version); // 版本号，全渠道默认值
		requestData.put("encoding", UnionConfig.encoding); // 字符集编码，可以使用UTF-8,GBK两种方式
		requestData.put("signMethod", UnionConfig.signMethod); // 签名方法
		requestData.put("txnType", "01"); // 交易类型 ，01：消费
		requestData.put("txnSubType", "01"); // 交易子类型， 01：自助消费
		requestData.put("bizType", "000201"); // 业务类型，B2C网关支付，手机wap支付
		requestData.put("channelType", "07"); // 渠道类型，这个字段区分B2C网关支付和手机wap支付;07:PC,平板;08:手机

		/*** 商户接入参数 ***/
		requestData.put("merId", company.getMerId()); // 商户号码，请改成自己申请的正式商户号或者open上注册得来的777测试商户号
		requestData.put("accessType", "0"); // 接入类型，0：直连商户
		requestData.put("orderId", company.getOrderId()); // 商户订单号，8-40位数字字母，不能含“-”或“_”，可以自行定制规则
		requestData.put("txnTime", company.getTxnTime()); // 订单发送时间，取系统时间，格式为YYYYMMDDhhmmss，必须取当前时间，否则会报txnTime无效
		requestData.put("currencyCode", "156"); // 交易币种（境内商户一般是156 人民币）
		requestData.put("txnAmt", company.getTxnAmt() + ""); // 交易金额，单位分，不要带小数点

		// 前台通知地址 （需设置为外网能访问 http https均可），支付成功后的页面 点击“返回商户”按钮的时候将异步通知报文post到该地址
		// 如果想要实现过几秒中自动跳转回商户页面权限，需联系银联业务申请开通自动返回商户权限
		// 异步通知参数详见open.unionpay.com帮助中心 下载 产品接口规范 网关支付产品接口规范 消费交易 商户通知
		requestData.put("frontUrl", company.getFrontUrl());

		// 后台通知地址（需设置为【外网】能访问 http
		// https均可），支付成功后银联会自动将异步通知报文post到商户上送的该地址，失败的交易银联不会发送后台通知
		// 后台通知参数详见open.unionpay.com帮助中心 下载 产品接口规范 网关支付产品接口规范 消费交易 商户通知
		// 注意:1.需设置为外网能访问，否则收不到通知 2.http https均可 3.收单后台通知后需要10秒内返回http200或302状态码
		// 4.如果银联通知服务器发送通知后10秒内未收到返回状态码或者应答码非http200，那么银联会间隔一段时间再次发送。总共发送5次，每次的间隔时间为0,1,2,4分钟。
		// 5.后台通知地址如果上送了带有？的参数，例如：http://abc/web?a=b&c=d
		// 在后台通知处理程序验证签名之前需要编写逻辑将这些字段去掉再验签，否则将会验签失败
		requestData.put("backUrl", company.getBackUrl());

		// 订单超时时间。
		// 超过此时间后，除网银交易外，其他交易银联系统会拒绝受理，提示超时。
		// 跳转银行网银交易如果超时后交易成功，会自动退款，大约5个工作日金额返还到持卡人账户。
		// 此时间建议取支付时的北京时间加15分钟。
		// 超过超时时间调查询接口应答origRespCode不是A6或者00的就可以判断为失败。
		requestData.put("payTimeout", company.getPayTimeout());
		return requestData;
	}
}
